#include "../Interfaces/Interfaz.h"
#include <limits>

using namespace Interfaces;

Interfaz::Interfaz() {
}

int Interfaz::menuPantallaInicio() {
	system("clear");
	cout << "BIENVENIDO A ELECCIONES" << endl;
	cout << "========================" << endl;
	cout << "Para cumplir su obligacion civica ";
	cout << "Por favor registrese" << endl;
	cout << "Elija tipo de Usuario: " << endl;
	cout << "			1-Administrador" << endl;
	cout << "			2-Votante" << endl;
	cout << endl;
	cout << "Si desea salir presione 9" << endl;
	cout << "Opcion: ";
	cin >> this->opcion;
	cout << endl;
	if (opcion == 9) {
		system("clear");
		cout << "La aplicación ha finalizado" << endl;
		return 0;
	} else {
		if (opcion == 1)
			this->menuAdministrador();
		else
			this->menuVotacionDeEleccion();

	}
}

int Interfaz::menuPantallaLogin() {
	cout << "Usuario: ";
	cin >> this->usuario;
	cout << " " << endl;
	cout << "contraseña: ";
	cin >> this->contrasenia;
	cout << " " << endl;
	if (!this->validarUsuarioYContraseniaAdmin(usuario, contrasenia, opcion)) {
		system("clear");
		cout << "Usuario/clave u opcion Incorrecta! Presione una tecla para continuar" << endl;
		system("paused");
		this->menuPantallaInicio();
	}
}

void Interfaz::menuAdministrador() {
	bool fin = false;

	while (!fin) {
		system("clear");
		int opcionAdm;
		cout << "Menu Administrador: " << endl;
		cout << "      1- ABM Votante" << endl;
		cout << "      2- ABM Distrito" << endl;
		cout << "      3- ABM Cargo" << endl;
		cout << "      4- ABM Eleccion" << endl;
		cout << "      5- ABM Candidato" << endl;
		cout << "      6- ABM Lista" << endl;
		cout << "      7- Ver Reportes" << endl;
		cout << "      8- Ver Logs" << endl;
		cout << "      9- Volver" << endl;
		cout << "Elija la opcion: ";
		cin >> opcionAdm;
		cout << endl;
		if ((opcionAdm > 0) && (opcionAdm <= 9)) {
			switch (opcionAdm) {
			case (1):
				this->menuABMVotante();
				break;
			case (2):
				this->menuABMDistrito();
				break;
			case (3):
				this->menuABMCargo();
				break;
			case (4):
				this->menuABMEleccion();
				break;
			case (5):
				this->menuABMCandidato();
				break;
			case (6):
				this->menuABMLista();
				break;
			case (7):
				this->menuReportes();
				break;
			case (8):
				this->menuLogs();
				break;
			case (9):
				this->menuPantallaInicio();
				fin = true;
				break;
			}
		} else {
			cout << "Opcion Incorrecta! Presione cualquier tecla para volver al Menu" << endl;
			getchar();
			getchar();
		}
	}
}

void Interfaz::menuABMVotante() {
	bool fin = false;
	while (!fin) {
		system("clear");
		int opcionVotante;
		cout << "VOTANTE" << endl;
		cout << "Elegir la opcion: " << endl;
		cout << "     1 - Alta" << endl;
		cout << "     2 - Baja" << endl;
		cout << "     3 - Modificacion" << endl;
		cout << "     4 - Volver al Menu anterior" << endl;
		cout << "Opcion: ";
		cin >> opcionVotante;
		if ((opcionVotante >= 1) && (opcionVotante <= 4)) {
			if (opcionVotante != 4)
				this->votanteABM(opcionVotante);
			else
				fin = true;
		} else {
			cout << "Opcion Incorrecta. Vuelva a intentarlo" << endl;
			getchar();
			getchar();
		}
	}
}

void Interfaz::menuABMDistrito() {
	bool fin = false;
	while (!fin) {
		system("clear");
		int opcionDistrito;
		cout << "DISTRITO" << endl;
		cout << "Elegir la opcion: " << endl;
		cout << "     1 - Alta" << endl;
		cout << "     2 - Baja" << endl;
		cout << "     3 - Modificacion" << endl;
		cout << "     4 - Volver al Menu anterior" << endl;
		cout << "Opcion: ";
		cin >> opcionDistrito;
		if ((opcionDistrito >= 1) && (opcionDistrito <= 4)) {
			if (opcionDistrito != 4)
				this->distritoABM(opcionDistrito);
			else
				fin = true;
		} else {
			cout << "Opcion incorrecta. Vuelva a intentarlo" << endl;
			getchar();
			getchar();
		}
	}
}

void Interfaz::menuABMCargo() {
	bool fin = false;
	while (!fin) {
		system("clear");
		int opcionCargo;
		cout << "CARGO" << endl;
		cout << "Elegir la opcion: " << endl;
		cout << "     1 - Alta" << endl;
		cout << "     2 - Baja" << endl;
		cout << "     3 - Modificacion" << endl;
		cout << "     4 - Volver al Menu anterior" << endl;
		cout << "Opcion: ";
		cin >> opcionCargo;
		if ((opcionCargo >= 1) && (opcionCargo <= 4)) {
			if (opcionCargo != 4)
				this->cargoABM(opcionCargo);
			else
				fin = true;
		} else {
			cout << "opcion incorrecta. Vuelva a intentarlo" << endl;
			getchar();
			getchar();
		}
	}
}

void Interfaz::menuABMEleccion() {
	system("clear");
	int opcionEleccion;
	cout << "ELECCION" << endl;
	cout << "Elegir la opcion: " << endl;
	cout << "     1 - Alta" << endl;
	cout << "     2 - Baja" << endl;
	cout << "     3 - Modificacion" << endl;
	cout << "     4 - Volver" << endl;
	cout << "Opcion: ";
	cin >> opcionEleccion;
	if ((opcionEleccion >= 1) && (opcionEleccion <= 3)) {
		this->eleccionABM(opcionEleccion);
	} else {
		if (opcionEleccion == 4)
			this->menuAdministrador();
		else {
			cout << "Opcion incorrecta. Vuelva a intentarlo";
			this->menuABMEleccion();
		}
	}
}
;

void Interfaz::menuABMCandidato() {
	int opcionCandidato;
	cout << "CANDIDATO" << endl;
	cout << "Elegir la opcion: " << endl;
	cout << "     1 - Alta" << endl;
	cout << "     2 - Baja" << endl;
	cout << "     3 - Modificacion" << endl;
	cout << "opcion: ";
	cin >> opcionCandidato;
	if ((opcionCandidato >= 1) && (opcionCandidato <= 3)) {
		this->candidatoABM(opcionCandidato);
	} else {
		cout << "opcion incorrecta. Vuelva a intentarlo";
		this->menuAdministrador();
	}
}
;

void Interfaz::menuABMLista() {
	int opcionLista;
	cout << "LISTA" << endl;
	cout << "Elegir la opcion: " << endl;
	cout << "     1 - Alta" << endl;
	cout << "     2 - Baja" << endl;
	cout << "     3 - Modificacion" << endl;
	cout << "opcion: ";
	cin >> opcionLista;
	if ((opcionLista >= 1) && (opcionLista <= 3)) {
		this->listaABM(opcionLista);
	} else {
		cout << "opcion incorrecta. Vuelva a intentarlo";
		this->menuAdministrador();
	}
}
;

void Interfaz::candidatoABM(int abm) {
	Candidato* candidato = new Candidato();
	ManejadorCandidato* manejadorCandidato = new ManejadorCandidato();
	string nombreCargo;
	string nombreLista;
	int fecha;
	int dni;
	cout << "ingrese nombre del CARGO: ";
	cin >> nombreCargo;
	candidato->setCargo(nombreCargo);//Esto no se debe validar con los cargos cargados y si no existe darlo de alta
	cout << "ingrese DNI: ";
	cin >> dni;
	candidato->setVotante(dni);
	cout << "ingrese FECHA de la Lista: ";
	cin >> fecha;
	cout << "ingrese NOMBRE de la LISTA: ";
	cin >> nombreLista;
	//TODO: validar una fecha valida
	candidato->setLista(fecha, nombreCargo, nombreLista);
	switch (abm) {
	case (1):
		if (manejadorCandidato->alta(candidato)) {
			cout << "Se ha ingresado el candidato correctamente.";
		} else {
			cout << "candidato no ingresado. Por favor vuelvalo a intentar.";
		}
		;
		break;
	case (2):
		if (manejadorCandidato->baja(candidato)) {
			cout << "Se ha borrado el candidato correctamente.";
		} else {
			cout << "candidato no borrado o No exite el candidato en la base. Por favor vuelvalo a intentar.";
		}
		;
		break;
	case (3):
		//TODO: Ver este caso ya que el manejador debiera buscar antes de modificar;
		break;
	}
}
void Interfaz::cargoABM(int abm) {

	Cargo* cargo = new Cargo();
	ManejadorCargo* manejadorCargo = new ManejadorCargo();
	string nombreCargo;
	cout << "Ingrese el nombre del CARGO: " << endl;
	cin >> nombreCargo;
	cargo->setNombre(nombreCargo);
	switch (abm) {
	case (1):
		if (manejadorCargo->alta(cargo)) {
			cout << "Se ha ingresado el cargo correctamente." << endl;
		} else {
			cout << "cargo no ingresado. Por favor vuelvalo a intentar." << endl;
		}
		break;
	case (2):
		if (manejadorCargo->baja(cargo)) {
			cout << "Se ha borrado el cargo correctamente." << endl;
		} else {
			cout << "cargo no borrado o No exite el cargo en la base. Por favor vuelvalo a intentar." << endl;
		}
		break;
	case (3):
		/*TODO: vamos a mostrar los datos del cargo a ver que modifica??
		 * No estamos teniendo en cuenta modificar la lista de cargos
		 */
		string nuevoNombre;
		string viejoNombre;

		cout << "ingrese el nuevo nombre del cargo" << endl;
		cin >> nuevoNombre;
		viejoNombre = cargo->getNombre();
		cargo->setNombre(nuevoNombre);

		if (manejadorCargo->modificacion(cargo, viejoNombre)) {
			cout << "Se ha modificado el cargo correctamente." << endl;
		} else {
			cout << "cargo no modificado o No exite el cargo en la base. Por favor vuelvalo a intentar." << endl;
		}
		break;
	}
	delete cargo;
	delete manejadorCargo;
}

void Interfaz::distritoABM(int abm) {
	bool fin = false;
	while (!fin) {
		system("clear");
		Distrito* distrito = new Distrito();
		ManejadorDistrito* manejadorDistrito = new ManejadorDistrito();

		string nombreDistrito;
		cout << "Ingrese el Distrito: ";
		cin >> nombreDistrito;
		distrito->setNombre(nombreDistrito);

		switch (abm) {
		case (1):
			if (manejadorDistrito->alta(distrito)) {
				cout << "Se ha ingresado el distrito correctamente." << endl;
			} else {
				cout << "Distrito existente"<<endl;
			}
		    fin = true;
			break;
		case (2):
			if (manejadorDistrito->baja(distrito)) {
				cout << "Se ha borrado el distrito correctamente." << endl;
			} else {
				cout<< "Distrito no borrado o No exite el distrito en la base. Por favor vuelvalo a intentar."<< endl;
			}
			fin = true;
			break;
		case (3):
			//TODO: Ver este caso ya que el manejador debiera buscar antes de modificar;
			//Se da de baja el que estaba y se da de alta el nuevo
			//El viejo se MARCA COMO BORRADO
			break;
		}
		delete distrito;
		delete manejadorDistrito;
		getchar();
		getchar();
	}
}

void Interfaz::eleccionABM(int abm) {

        bool existenLosIdentificadoresExternos = true;
        bool realizoOperacion = false;
        ManejadorEleccion* manejadorEleccion = new ManejadorEleccion();
        ManejadorDistrito* manejadorDistrito = new ManejadorDistrito();
        ManejadorCargo* manejadorCargo = new ManejadorCargo();
        int fecha = -1;
        string cargo = "";
        string distrito = "";
        unsigned int distritosParaAgregar = 0;

        system("clear");
        cout << "Ingrese la FECHA de la eleccion: ";
        cin >> fecha;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        cout << endl << "Ingrese el nombre del CARGO: ";
        getline(cin, cargo);

        existenLosIdentificadoresExternos = manejadorCargo->existe(cargo);

        if (existenLosIdentificadoresExternos) {
                switch (abm) {
                case (1): {

                        Eleccion* eleccionAInsertar = new Eleccion();
                        eleccionAInsertar->setFecha(fecha);
                        eleccionAInsertar->setCargo(cargo);

                        cout << endl << "Ingrese cuantos distritos desea agregar: ";
                        cin >> distritosParaAgregar;
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');

                        for (unsigned int i = 0; i < distritosParaAgregar; i++) {
                                cout << endl << "Ingrese el nombre del DISTRITO no" << i << " a agregar: ";
                                getline(cin, distrito);

                                if (manejadorDistrito->existe(distrito))
                                        eleccionAInsertar->agregarDistrito(distrito);
                                else {
                                        existenLosIdentificadoresExternos = false;
                                        break;
                                }
                        }

                        if (existenLosIdentificadoresExternos && manejadorEleccion->alta(eleccionAInsertar)) {
                                cout << endl << "Se ha ingresado el eleccion correctamente";
                                realizoOperacion = true;
                        }

                        delete eleccionAInsertar;
                        break;
                }
                case (2): {

                        Eleccion* eleccionABorrar = new Eleccion();
                        eleccionABorrar->setFecha(fecha);
                        eleccionABorrar->setCargo(cargo);

                        if (manejadorEleccion->baja(eleccionABorrar)) {
                                cout << endl << "Se ha borrado la eleccion correctamente";
                                realizoOperacion = true;
                        }

                        delete eleccionABorrar;
                        break;
                }
                case (3): {

                        Eleccion* eleccionAModificar = new Eleccion();
                        eleccionAModificar->setFecha(fecha);
                        eleccionAModificar->setCargo(cargo);

                        Eleccion* eleccionModificada = new Eleccion(eleccionAModificar);

                        bool existenLosIdentificadoresExternos = this->modificarEleccion(eleccionModificada);

                        if (existenLosIdentificadoresExternos && manejadorEleccion->modificacion(eleccionAModificar,
                                        eleccionModificada)) {
                                cout << endl << "Se ha modificada la eleccion correctamente";
                                realizoOperacion = true;
                        }

                        delete eleccionAModificar;
                        delete eleccionModificada;
                        break;

                }
                }
        }

        if (!existenLosIdentificadoresExternos || !realizoOperacion) {

                cout << endl << "Eleccion no modificada. Los datos ingresados para modificar no son correctos";
                cout << "Por favor vuelvalo a intentar";
                cout << endl << "Presione <Enter> para continuar...";
                cin.ignore();
        }

        delete manejadorDistrito;
        delete manejadorEleccion;
        delete manejadorCargo;
        this->menuABMEleccion();
}

bool Interfaz::modificarEleccion(Eleccion* eleccion) {

        ManejadorDistrito* manejadorDistrito = new ManejadorDistrito();
        ManejadorCargo* manejadorCargo = new ManejadorCargo();
        unsigned int campoAModificar = 0;
        bool sigue = true;

        system("clear");
        cout << "Ingrese el campo que desea modificar " << endl;
        cout << "               1- Fecha" << endl;
        cout << "               2- Cargo" << endl;
        cout << "               3- Distritos" << endl;
        cout << "       4- Volver" << endl;
        cin >> campoAModificar;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        switch (campoAModificar) {
        case (1): {
                unsigned int fecha = -1;
                cout << endl << "Ingrese la FECHA de la eleccion: ";
                cin >> fecha;
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                eleccion->setFecha(fecha);
                break;
        }
        case (2): {
                string cargo = "";
                cout << endl << "Ingrese el nombre del CARGO: ";
                getline(cin, cargo);

                if (manejadorCargo->existe(cargo))
                        eleccion->setCargo(cargo);
                else
                        cout << endl << "El cargo ingresado no existe ";

                break;
        }
        case (3): {
                unsigned int distritosParaAgregar = 0;
                cout << endl << "Ingrese cuantos distritos desea agregar: ";
                cin >> distritosParaAgregar;
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                for (unsigned int i = 0; i < distritosParaAgregar; i++) {
                        string distrito = "";
                        cout << endl << "Ingrese el nombre del DISTRITO no" << i << " a agregar: ";
                        getline(cin, distrito);

                        if (manejadorDistrito->existe(distrito))
                                eleccion->agregarDistrito(distrito);
                        else
                                cout << endl << "El distrito ingresado no existe ";
                }
                break;
        }
        case (4): {
                sigue = false;
        }
        default: {
                cout << endl << "Opcion incorrecta" << endl;
                break;
        }
        }

        return sigue;
}

void Interfaz::listaABM(int abm) {
	Lista* lista = new Lista();
	Cargo* cargoAComparar = new Cargo();
	ManejadorLista* manejadorLista = new ManejadorLista();
	ManejadorCargo* manejadorCargo = new ManejadorCargo();
	string nombreDeLaLista;
	int fecha;
	string cargo;
	cout << "ingrese el NOMBRE de la LISTA: ";
	cin >> nombreDeLaLista;
	cout << endl;
	cout << "ingrese la eleccion" << endl;
	cout << "       FECHA: ";
	cin >> fecha;
	cout << endl;
	cout << "       CARGO: ";
	cin >> cargo;
	cout << endl;
	lista->setNombre(nombreDeLaLista);
	lista->setEleccion(fecha, cargo);
	//	cargoAComparar = manejadorCargo->recuperar(cargo);
	if (cargo == cargoAComparar->getNombre()) {
		switch (abm) {
		case (1):
			if (manejadorLista->alta(lista))
				cout << "Se ha ingresado el lista correctamente.";
			else
				cout << "lista no ingresado. Por favor vuelvalo a intentar.";
			break;
		case (2):
			if (manejadorLista->baja(lista))
				cout << "Se ha borrado el lista correctamente.";
			else
				cout << "lista no borrado o No exite el lista en la base. Por favor vuelvalo a intentar.";
			break;
		case (3):
			cout << "Modificando Lista..." << endl;
			cout << "ingrese nombre de la LISTA modificada: ";
			cin >> nombreDeLaLista;
			cout << endl;
			cout << "ingrese la eleccion" << endl;
			cout << "       FECHA: ";
			cin >> fecha;
			cout << endl;
			cout << "       CARGO: ";
			cin >> cargo;
			cout << endl;
			lista->setNombre(nombreDeLaLista);
			lista->setEleccion(fecha, cargo);
			if (manejadorLista->modificacion(lista))
				cout << "La modificacion fue realizada exitosamente.";
			else {
				cout << "Se produjo un error intentando modificar";
				cout << "Por favor. Vuelva a intentarlo" << endl;
			}
			break;
		}
	} else {
		cout << "Error al buscar entidades relacionadas.";
		cout << "Por favor revise los datos ingresados";
		system("clear");
	}
	this->menuABMLista();
}

void Interfaz::votanteABM(int abm) {
	bool fin = false;
	while (!fin) {
		system("clear");
		Votante* votante = new Votante(); //TODO:: lo borro aca por ahora
		ManejadorVotante* manejadorVotante = new ManejadorVotante();
		string nombreYApellido;
		string domicilio;
		string distritoVotante;
		int dni; //TODO::OJO! si pone caracteres ROMPE todo
		int clave;
		cout << "ABM VOTANTE " << endl;
		cout << endl;
		cout << "Ingrese el DNI: ";
		cin >> dni;
		cout << endl;
		votante->setDNI(dni);

		switch (abm) {
		case (1):
			cout << "Ingrese el NOMBRE y APELLIDO: ";
			cin >> nombreYApellido;
			cout << endl;
			cout << "Ingrese DOMICILIO: ";
			cin >> domicilio;
			cout << endl;
			cout << "Ingrese el DISTRITO: ";
			cin >> distritoVotante;
			cout << endl;
			cout << "ingrese la CLAVE: ";
			cin >> clave;
			cout << endl;
			votante->setNombreYApellido(nombreYApellido);
			votante->setDomicilio(domicilio);
			votante->setDistrito(distritoVotante);

			votante->setClave(clave);
			if (manejadorVotante->alta(votante)) {
				cout << "Se ha ingresado el votante correctamente." << endl;
			} else {
				cout << "Votante ya ingresado";
			}
			fin = true;
			break;
		case (2):
			if (manejadorVotante->baja(votante)) {
				cout << "Se ha borrado el votante correctamente." << endl;
			} else {
				cout
						<< "No exite el votante que se desae eliminar. Por favor vuelvalo a intentar."
						<< endl;
			}
			fin = true;
			break;
		case (3):
			//TODO: Ver este caso ya que el manejador debiera buscar antes de modificar;

			break;
		case (-1):
			cout << "Distrito invalido, vuelva a realizar su ingreso" << endl;
			break;
		}
		delete votante;
		delete manejadorVotante;
		getchar();
		getchar();
	}
}

void Interfaz::menuReportes() {

}

void Interfaz::menuLogs() {

}

void Interfaz::menuVotacionDeEleccion() {

}

bool Interfaz::validarUsuarioYContraseniaAdmin(string usuario, string contrasenia, int tipoUsuario) {
	ManejadorAdministrador* manejadorAdministrador = new ManejadorAdministrador();
	if (tipoUsuario == 1) {
		Administrador* administrador = manejadorAdministrador->recuperar(usuario);
		bool validar = administrador->validarContrasenia(contrasenia);
		delete administrador;
		return validar;
	} else
		return false;

}

Interfaz::~Interfaz() {
}
